/**
 *******************************************************************************
 *                 Copyright (C) 2017 - 2022  Accumulate Team                  *
 *                                                                             *
 *      Licensed under the Apache License, Version 2.0 (the "License");        *
 *      you may not use this file except in compliance with the License.       *
 *      You may obtain a copy of the License at                                *
 *                 http://www.apache.org/licenses/LICENSE-2.0                  *
 *                                                                             *
 *   Unless required by applicable law or agreed to in writing, software       *
 *   distributed under the License is distributed on an "AS IS" BASIS,         *
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 *   See the License for the specific language governing permissions and       *
 *   limitations under the License.                                            *
 *******************************************************************************
 * @file       sm_list.h                                                       *
 * @author     Accumulate Team                                                 *
 * @version    1.0.0                                                           *
 * @date       2017-01-10                                                      *
 * @brief      framework state machine list component head file                *
 * @par        work platform                                                   *
 *                 Windows                                                     *
 * @par        compiler                                                        *
 *                 GCC                                                         *
 *******************************************************************************
 * @note                                                                       *
 * 1.20170110    链表组件移植于RT-THREAD                                       *
 *******************************************************************************
 */

/**
 * @defgroup framework state machine list component
 * @{
 */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STATE_MACHINE_LIST_H__
#define __STATE_MACHINE_LIST_H__

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include <stdint.h>

/* Add c++ compatibility -----------------------------------------------------*/
#ifdef __cplusplus
extern "C"
{
#endif

/* Exported macro ------------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief      MACRO
 *******************************************************************************
 */
#ifndef _container_of
#define _container_of(ptr, type, member) \
               ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
#endif

/* Exported types ------------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief      状态机节点 数据结构
 *******************************************************************************
 */
typedef struct SM_LIST_NODE
{
    struct SM_LIST_NODE *next;
    struct SM_LIST_NODE *prev;
}sm_list_t;

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/**
 * @brief initialize a list
 *
 * @param l list to be initialized
 */
static inline
void sm_list_init(sm_list_t *l)
{
    l->next = l->prev = l;
}

/**
 * @brief insert a node after a list
 *
 * @param l list to insert it
 * @param n new node to be inserted
 */
static inline
void sm_list_insert_after(sm_list_t *l, sm_list_t *n)
{
    l->next->prev = n;
    n->next = l->next;

    l->next = n;
    n->prev = l;
}

/**
 * @brief insert a node before a list
 *
 * @param n new node to be inserted
 * @param l list to insert it
 */
static inline
void sm_list_insert_before(sm_list_t *l, sm_list_t *n)
{
    l->prev->next = n;
    n->prev = l->prev;

    l->prev = n;
    n->next = l;
}

#define sm_list_append sm_list_insert_before

/**
 * @brief remove node from list.
 * @param n the node to remove from the list.
 */
static inline
void sm_list_remove(sm_list_t *n)
{
    n->next->prev = n->prev;
    n->prev->next = n->next;

    n->next = n->prev = n;
}

/**
 * @brief tests whether a list is empty
 * @param l the list to test.
 */
static inline
int sm_list_isempty(const sm_list_t *l)
{
    return l->next == l;
}

/**
 * @brief get the list length
 * @param l the list to get.
 */
static inline
unsigned int sm_list_len(const sm_list_t *l)
{
    unsigned int len = 0;
    const sm_list_t *p = l;
    while (p->next != l)
    {
        p = p->next;
        len ++;
    }

    return len;
}

/**
 * sm_list_for_each - iterate over a list
 * @pos:    the sm_list_t * to use as a loop cursor.
 * @head:   the head for your list.
 */
#define sm_list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

/**
 * sm_list_for_each_safe - iterate over a list safe against removal of list entry
 * @pos:    the sm_list_t * to use as a loop cursor.
 * @n:      another sm_list_t * to use as temporary storage
 * @head:   the head for your list.
 */
#define sm_list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)

/**
 * sm_list_for_each_entry  -   iterate over list of given type
 * @pos:    the type * to use as a loop cursor.
 * @head:   the head for your list.
 * @member: the name of the list_struct within the struct.
 */
#define sm_list_for_each_entry(pos, head, type, member) \
    for (type *pos = _container_of(((sm_list_t *)head)->next, type, member); \
         &pos->member != ((sm_list_t *)head) && !sm_list_isempty(head); \
         pos = _container_of(pos->member.next, type, member))

/* Add c++ compatibility------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
	
#endif       /** end include define */

/** @}*/     /** framework state machine list component */

/**********************************END OF FILE*********************************/
